package net.xo68.destiny.manager.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import net.xo68.destiny.contract.api.ManagerApi;
import net.xo68.destiny.contract.common.SystemConstants;
import net.xo68.destiny.contract.domain.RespondResult;
import net.xo68.destiny.contract.domain.StringRespondResult;
import net.xo68.destiny.contract.domain.node.NodeRegistry;
import net.xo68.destiny.contract.domain.report.JobHandleReplyDatagram;
import net.xo68.destiny.core.discovery.NodeDiscoveryClient;
import net.xo68.destiny.core.eventbus.EventBusManager;
import net.xo68.destiny.core.util.IpUtil;
import net.xo68.destiny.starter.manager.SchedulerManagerProperties;
import net.xo68.destiny.starter.manager.enums.MessageEventTypeEnum;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;

@Slf4j
@Api(tags = "管理节点接口控制器")
@RequestMapping("/api")
@RestController
public class ManagerApiController implements ManagerApi {

    @Autowired
    private SchedulerManagerProperties schedulerManagerProperties;
    @Autowired
    private EventBusManager eventBusManager;
    @Autowired
    private NodeDiscoveryClient nodeDiscoveryClient;

    @Override
    @GetMapping("/discovery")
    @ApiOperation(value = "节点信息")
    public RespondResult<List<NodeRegistry>> discovery(@RequestParam(value = "workGroupName", defaultValue = SystemConstants.DEFAULT_WORK_GROUP) String workGroupName){
        //final List<NodeHeartbeat> list = nodeHeartbeatService.validList(schedulerManagerProperties.getHeartbeatPeriodSecond() * 3L);
        final List<NodeRegistry> nodeRegistryList=new ArrayList<>();
        Iterator<NodeRegistry> manageIter = nodeDiscoveryClient.getManageNodes().iterator();
        while (manageIter.hasNext()){
            NodeRegistry nodeRegistry=manageIter.next();
            nodeRegistryList.add(nodeRegistry);
        }
        Iterator<NodeRegistry> workIter=nodeDiscoveryClient.getWorkNodesByGroupName(workGroupName).iterator();
        while (workIter.hasNext()){
            NodeRegistry nodeRegistry=workIter.next();
            nodeRegistryList.add(nodeRegistry);
        }
        return RespondResult.ok(nodeRegistryList);
    }

    @Override
    @PostMapping("/heartbeat")
    @ApiOperation(value = "工作节点注册（心跳）")
    public StringRespondResult workerHeartbeat(@RequestBody NodeRegistry nodeRegistry){
        log.debug("workerHeartbeat {}",nodeRegistry);
        String nodeHost=nodeRegistry.getNodeHost();
        if(StringUtils.isBlank(nodeHost) || StringUtils.isBlank(nodeRegistry.getWorkGroup())){
            log.error("节点注册信息不合法,node: {}",nodeRegistry);
            return StringRespondResult.fail();
        }
        String nodeIp=nodeHost.substring(0,nodeHost.indexOf(":"));
        if(!IpUtil.validIpV4Address(nodeIp) || !validIp(nodeIp)){
            log.error("节点注册Ip不合法,nodeIp: {}",nodeIp);
            return StringRespondResult.fail();
        }
        eventBusManager.publish(MessageEventTypeEnum.NODE_REGISTRY.getCode(), nodeRegistry);
        return StringRespondResult.ok();
    }

    /**
     * 检验ip是否在匹配配置的Ip范围内
     * @param ipAddress
     * @return
     */
    private boolean validIp(String ipAddress){
        if(IpUtil.ANYHOST_VALUE.equals(ipAddress) || IpUtil.LOCALHOST_VALUE.equals(ipAddress)){
            return false;
        }
        final List<String> patterns=schedulerManagerProperties.nodePatterns();
        if(patterns==null || patterns.isEmpty()){
            return true;
        }
        for (String patternStr : patterns){
            Pattern pattern=Pattern.compile(patternStr);
            if(pattern.matcher(ipAddress).matches()){
                return true;
            }
        }
        return false;
    }

    @Override
    @PostMapping("/downline")
    @ApiOperation(value = "工作节点下线")
    public StringRespondResult workerDownline(@RequestBody NodeRegistry nodeRegistry){
        log.debug("workerDownline {}",nodeRegistry);
        eventBusManager.publish(MessageEventTypeEnum.NODE_DOWNLINE.getCode(), nodeRegistry);
        return StringRespondResult.ok();
    }

    @Override
    @PostMapping("/jobState")
    @ApiOperation(value = "工作节点任务状态上报")
    public StringRespondResult jobState(@RequestBody List<JobHandleReplyDatagram> replyDatagramList){
        //log.debug("job state report: {}",replyDatagramList);
        eventBusManager.publish(MessageEventTypeEnum.JOB_STATE_REPORT.getCode(), replyDatagramList);
        return StringRespondResult.ok();
    }
}
